#include "stdafx.h"

#include <Algorithm.h>
#include <IntegerCounter.h>

#include "Package.h"
#include "Packer.h"
#include "Des.h"

using namespace Algorithm;
using namespace OperationMode;

Packer::Packer(const byte *key)
{
    memcpy(this->key, key, 8);
}

void Packer::ecrypt(const byte *data, uint64 Size, byte *outData)
{
    uint64 paddedSize = pad(Size);
    byte *paddedData = new byte[paddedSize * 2];
    byte *ecryptedData = paddedData + paddedSize;
    memcpy(paddedData, data, Size);

    byte iv[8];
    Algorithm::Random::generate(iv, 8);

    IntegerCounter<Des> ecryptor(iv, key, Direction::Ecryption);
    ecryptor.process(paddedData, paddedSize, ecryptedData);

    EcryptionPackageV1::pack(ecryptedData, iv, Size, paddedSize, outData);
}

void Packer::decrypt(const byte* data, byte *outData)
{
    EcryptionPackageV1 package(data);
    package.ecryptedData();

    IntegerCounter<Des> decryptor(package.initializeVector(), key, Direction::Ecryption);
    decryptor.process(package.ecryptedData(), package.ecryptedDataSize(), outData);
}

uint64 Packer::pad(uint64 dataSuze)
{
    return (dataSuze + Des::BlockSize - 1) / Des::BlockSize * Des::BlockSize;
}

uint64 Packer::ecryptedSize(uint64 dataSize)
{
    return EcryptionPackageV1::packagedSize(pad(dataSize));
}

uint64 Packer::decryptedSize(const byte *ecryptedData)
{
    return EcryptionPackageV1(ecryptedData).origignalDataSize();
}
